package com.cea.papyrus.diagram.classdiagram.helper;

import java.util.ArrayList;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.UMLPackage;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.helper.NodeHelper;
import com.cea.papyrus.core.preference.ClassDiagramCommonPreferenceConstants;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Factory that can create and delete an {@link Operation}}.
 * @author Arnaud Cuccuru
 */
public class NodeRedefinableTemplateSignatureHelper extends NodeHelper {
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#createGraphElement(org.eclipse.uml2.uml.Element, com.cea.papyrus.diagraminterchange2.di2.GraphElement, org.eclipse.draw2d.geometry.Point, org.eclipse.draw2d.geometry.Dimension)
	 */
	@Override
	public GraphNode createGraphElement(Element umlChild, GraphElement parent, Point location, Dimension size) {
		Debug.debug(this,"Call NodeOperationFactory.createGraphElement()", channel); //$NON-NLS-1$
		
		//Defines the size of the graph node containing the dashed box figure ;
		if (size == null) {
			Dimension dim = new Dimension() ;
			dim.height = 35 ;
			dim.width = Math.max(((GraphNode)parent).getSize().width / 3, 75) ;
			size = dim ;
		}
		
		//sets the position of the graphnode to the upper right corner of the parent graphnode
		Point newLocation = new Point() ;
		Point parentLocation = parent.getPosition() ;
		newLocation.x = parentLocation.x + ((GraphNode)parent).getSize().width - (size.width / 3) ;
		newLocation.y = parentLocation.y - 20;
		
		
		// creates the graph element corresponding to the TemplateSignature
		GraphNode graphNode = super.createGraphElement(umlChild, parent.getContainer(), newLocation, size);
		for (int i=0;i<1;i++){//Acha graphNode for each possible compartment
			GraphElement gN=super.createGraphElement(null,graphNode,null,null);
		}
		
		graphNode.setSemanticParent(parent) ;
		graphNode.setContainer(parent.getContainer()) ;
		
		//the ge parent is connected in last becaus an event may be sent at this moment and trigger a refresh.
//		if(parent != null) {
//			parent.getContained().add(graphNode);
//		}
		return graphNode;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.INodeFactory#createGraphNode(org.eclipse.uml2.uml.NamedElement, com.cea.papyrus.diagraminterchange2.di2.Diagram)
	 */
	@Override
	public ArrayList createGraphNode(Element umlElement, Diagram diagram) {
		return new ArrayList();
	}
	
	///**
	// * Returns the label of an operation
	// * @param o the operation to calculate
	// * @return the label of this operation 
	// * @deprecated use {@link com.cea.utils.Operation#getLabel(int) }instead
	// */
	//@Deprecated
	//public String getString(TemplateSignature o) {
	//	return getString(new com.cea.utils.TemplateSignature(o));
	//}
	
	/**
	 * Returns the label of a template signature
	 * @param t the template signature to calculate
	 * @return the label of this template signature 
	 */
	public String getString(com.cea.papyrus.umlutils.TemplateSignature t){
		//return t.getLabel();
		return "Template Signature" ;
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#canExecuteCreateCommand(com.cea.papyrus.diagraminterchange2.di2.GraphNode)
	 */
	@Override
	public boolean canCreateGraphElement(GraphElement parent){
 
		Element eltSource=null;
		if (parent.getSemanticModel()!=null ){
			if (((Uml1SemanticModelBridge)parent.getSemanticModel()).getElement()!=null){
				eltSource=((Uml1SemanticModelBridge)parent.getSemanticModel()).getElement();
//				if (eltSource instanceof TemplateableElement){// they are  classifiers
//					return true;
//				}
				//return canCreateUMLElement(eltSource) ;
				return true;
			}
		}
		return false;
	}
	
	///////////////////////////////////////////////////////////////////////////
	// UML Management
	///////////////////////////////////////////////////////////////////////////
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#createElement(java.lang.String, org.eclipse.uml2.uml.umlElement)
	 */
	@Override
	public org.eclipse.uml2.uml.Element createUMLElement(String name, org.eclipse.uml2.uml.Element umlParent){
		Debug.debug(this,"Call NodeTemplateSignatureFactory.createElement()", channel); //$NON-NLS-1$
		org.eclipse.uml2.uml.TemplateSignature templateSignature=null;
		//if (umlParent instanceof org.eclipse.uml2.uml.TemplateableElement) {
		templateSignature = ((org.eclipse.uml2.uml.Classifier)umlParent).createOwnedTemplateSignature(UMLPackage.eINSTANCE.getRedefinableTemplateSignature()) ;
		//}
		return templateSignature;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#canExecuteCreateElement(org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean canCreateUMLElement(Element umlParent) {
		if(umlParent instanceof org.eclipse.uml2.uml.Classifier) {
//			if (((org.eclipse.uml2.uml.TemplateableElement)umlParent).getOwnedTemplateSignature()==null )
				// tests if a template signature is already defined
				return true ;
		}
		return false ;
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#addElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean addUMLElement(Element element, Element umlParent) {
		if(umlParent instanceof org.eclipse.uml2.uml.TemplateableElement) {
			((org.eclipse.uml2.uml.TemplateableElement)umlParent).setOwnedTemplateSignature((org.eclipse.uml2.uml.TemplateSignature)element);
			return true;
		}
		return false;
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#removeElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	@Override
	public boolean removeUMLElement(Element element, Element umlParent) {
		if(umlParent instanceof org.eclipse.uml2.uml.TemplateableElement) {
			((org.eclipse.uml2.uml.TemplateableElement)umlParent).setOwnedTemplateSignature(null);
			return true;
		}
		return false;
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#getBaseString()
	 */
	@Override
	public String getBaseString() {
		return "TemplateSignature_"; //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.NodeHelper#setGraphElementPreferences(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	@Override
	public void setGraphElementPreferences(GraphElement graphElement) {
		// Get the preference store
		IPreferenceStore store = PapyrusPlugin.getDefault().getPreferenceStore();
		
		// Set colors and font
		graphElement.setBackgroundColor(ClassDiagramCommonPreferenceConstants.getPreferenceOperationBackgroundColor(store));
		graphElement.setBorderColor(ClassDiagramCommonPreferenceConstants.getPreferenceOperationBorderColor(store));
		graphElement.setFontColor(ClassDiagramCommonPreferenceConstants.getPreferenceOperationFontColor(store));
		FontData[] fontdata = ClassDiagramCommonPreferenceConstants.getPreferenceOperationFont(store);
		if (fontdata.length>0){
			graphElement.setFontFamily(fontdata[0].getName());
			graphElement.setFontSize(fontdata[0].getHeight());
		}
	}
	
	/**
	 * 
	 * 
	 * @param child 
	 * @param parent 
	 * 
	 * @return 
	 */
	public boolean removeGraphElement(GraphElement child, GraphElement parent){
		child.setSemanticParent(null);
		child.eAdapters().clear();
		 child.getContainer().getContained().remove(child);
		 return true;
	}
	
	/**
	 * this method calculate the good position of a port by taking account of his parent.
	 * 
	 * @param portDimension the dimension of the port
	 * @param parentGP graphNode the virtual graphNode that contains the port
	 * @param point the absolute position
	 * 
	 * @return the new position of the port.
	 */
	public Point inRunner(GraphNode parentGP,Point point, Dimension templateSignatureDimension){
		int x= point.x;
		int y= point.y;
		Point selected =point.getCopy();
		//calculate absolute position of GP
		Point positionGP=LookForElement.calculateAbsolutePosition(parentGP,new Point(0,0));

		// position is constraint in the parent rectangle
		// WEST
		if (x<positionGP.x +parentGP.getSize().width -templateSignatureDimension.width+5){
			x=positionGP.x +parentGP.getSize().width-templateSignatureDimension.width+5;
		}
		// EAST
		if (x>positionGP.x+parentGP.getSize().width-5){
			x=positionGP.x+parentGP.getSize().width-5;
		}
		// NORTH
		if (y<positionGP.y - templateSignatureDimension.height){
			y=positionGP.y - templateSignatureDimension.height;
		}
		// SOUTH
		if (y>positionGP.y){
			y=positionGP.y;
		}
		
		selected.x = x ;
		selected.y = y ;
		return selected;
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.NodeHelper#addGraphElement(com.cea.papyrus.diagraminterchange2.di2.GraphElement, com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	@Override
	public GraphElement addGraphElement(GraphElement child, GraphElement parent) {
		child.setSemanticParent(parent);
		if (child.getSemanticParent().getContainer() != null) {
			child.getSemanticParent().getContainer().getContained().add(child);
		} 
//		else {
//			defaultContainer.getContained().add(child);
//		}
		return child;
	}
}